#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>

class MMapFileParser {
public:
	int *JC, *CP, *ir_offset, *IR_PTR, fd, curr, JC_SIZE, IR_SIZE, count,
			*COUNTS;
	float *num_offset, *NUM_PTR;
	struct stat fs;
	void * map;

	void init() {
		int CP_SIZE;
		this->ir_offset = (int *) this->map;

		this->JC_SIZE = this->ir_offset[0];
		CP_SIZE = this->ir_offset[1];
		IR_SIZE = this->ir_offset[2];

		this->JC = (int*) malloc(this->JC_SIZE * sizeof(int));
		this->CP = (int*) malloc(CP_SIZE * sizeof(int));

		memcpy(this->JC, (this->ir_offset + 4), JC_SIZE * sizeof(int));
		memcpy(this->CP, (this->ir_offset + 4 + JC_SIZE),
				CP_SIZE * sizeof(int));
		COUNTS = (int*) malloc(sizeof(int) * (JC_SIZE+1));
		int max = -1;
		for (int i = 0; i < JC_SIZE; i++) {
			COUNTS[i] = CP[i + 1] - CP[i];
			if (COUNTS[i] > max)
				max = COUNTS[i];
		}
		COUNTS[JC_SIZE] = max;

		/*		for (int j = 0; j < JC_SIZE; j++) {
		 fprintf(stderr,"%d ", COUNTS[j]);
		 }*/
		ir_offset += 4 + JC_SIZE + CP_SIZE;
		num_offset = (float*) (ir_offset + IR_SIZE);

		fprintf(stderr,"finished mmap init\n", "");
		curr = 0;
	}

	MMapFileParser(char * filename) {
		this->fd = open(filename, O_RDONLY);

		if (fd == -1) {
			perror("Error opening file for reading");
			exit (EXIT_FAILURE);
		}

		if (fstat(fd, &fs) == -1) {
			perror("Error on fstat");
			exit (EXIT_FAILURE);
		}
		fprintf(stderr,"Opening file: %d kb\n", (int) fs.st_size);
		map = mmap(0, fs.st_size, PROT_READ, MAP_SHARED, fd, 0);

		if (map == MAP_FAILED) {
			close(fd);
			perror("Error mmapping the file");
			exit (EXIT_FAILURE);
		}
		init();
	}

	bool getinput() {
		if (JC[curr] != -1) {
			//fprintf(stderr,"getting input\n");
			int ir_begin = CP[curr];
			int ir_end = CP[curr + 1];
			count = ir_end - ir_begin;
			IR_PTR = (ir_offset + ir_begin);
			NUM_PTR = (float*) (num_offset + ir_begin);
			JC[curr] = -1;
			curr = (curr + 1) % JC_SIZE;
			return true;
		} else {
			if (munmap(map, fs.st_size) == -1) {
						perror("Error un-mmapping the file");
					}
					close(this->fd);
			return false;
		}
	}
};
